package com.qd.panda.service.stroke.order;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.core.weixinmanager.model.MiddleUser;
import com.cdqidi.core.weixinmanager.service.MiddleUserService;
import com.cdqidi.dto.ApiResultWrapper;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.DateUtil;
import com.qd.common.panda.config.PandaParkConfigDTO;
import com.qd.common.panda.domain.entity.stroke.UserStrokeOrderMallDTO;
import com.qd.common.panda.domain.entity.stroke.UserStrokeOrderRetryDTO;
import com.qd.common.sys.util.SecurityUtils;
import com.qd.panda.model.Commodity;
import com.qd.panda.model.UserStrokeOrder;
import com.qd.panda.service.commodity.CommodityService;
import com.qd.panda.service.stroke.DisplayUtil;
import com.qd.panda.service.third.dc.DataCenterService;
import com.qd.panda.service.third.dc.dto.OrderReqDTO;
import com.qd.system.model.BaseUserInfo;
import com.qd.system.service.user.BaseUserInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author sjk
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MallRetryService {

    private final UserStrokeOrderService userStrokeOrderService;
    private final UserStrokeOrderMallService userStrokeOrderMallService;
    private final UserStrokeOrderRetryService userStrokeOrderRetryService;
    private final DataCenterService dataCenterService;
    private final CommodityService commodityService;
    private final BaseUserInfoService baseUserInfoService;
    private final PandaParkConfigDTO pandaParkConfig;
    @Resource
    private MiddleUserService middleUserService;
    @Value("${dc.syncConfigCode}")
    private String syncConfigCode;
    private final Lock lock = new ReentrantLock();

    /**
     * 重试请求数据中心创建购物订单
     *
     * @param orderId 订单ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void retry(String orderId) {
        lock.lock();
        try{
            UserStrokeOrder userStrokeOrder = Optional.ofNullable(userStrokeOrderService.getById(orderId)).orElseThrow(() -> new ApiException("订单ID值错误"));
            if (!userStrokeOrder.getPayStatus().equals(DisplayUtil.PAY_STATUS_1)) {
                throw new ApiException("当前订单状态不能重试");
            }
            UserStrokeOrderMallDTO userStrokeOrderMall = Optional.ofNullable(userStrokeOrderMallService.getByIdDto(orderId)).orElseThrow(() -> new ApiException("订单ID值错误"));
            if (userStrokeOrderMall.getOrderState().equals(ApiResultWrapper.SUCCESS)) {
                throw new ApiException("订单已经成功,请勿重试");
            }
            UserStrokeOrderRetryDTO userStrokeOrderRetry = new UserStrokeOrderRetryDTO();
            userStrokeOrderRetry.setOrderId(orderId);
            userStrokeOrderRetry.setOrderType(DisplayUtil.ORDER_TYPE_5);
            userStrokeOrderRetry.setAddTime(LocalDateTime.now());
            userStrokeOrderRetry.setHandlePersonId(SecurityUtils.getLoginUser().getUserId());
            userStrokeOrderRetry.setHandleOrgId(SecurityUtils.getLoginUser().getCurrentOrgId());
            try {
                ApiResultWrapper<Object> apiResultWrapper = createOrder(userStrokeOrderMall, userStrokeOrder);
                userStrokeOrderRetry.setStateCode(apiResultWrapper.getCode());
                if (apiResultWrapper.isSuccess()) {
                    userStrokeOrderMall.setRetry(ConstantDto.SF1);
                    userStrokeOrderMallService.update(userStrokeOrderMall);
                }else{
                    userStrokeOrderRetry.setErrMsg(apiResultWrapper.getMsg());
                }
            } catch (Exception e) {
                log.error("访问数据中心创建订单失败", e);
                throw new ApiException("访问数据中心创建订单失败: "+ExceptionUtil.getMessage(e));
            }
            userStrokeOrderRetryService.save(userStrokeOrderRetry);
            userStrokeOrderRetry.freeData();
            userStrokeOrderMall.freeData();
            userStrokeOrder.freeData();
        }finally {
            lock.unlock();
        }
    }

    private ApiResultWrapper<Object> createOrder(UserStrokeOrderMallDTO userStrokeOrderMall, UserStrokeOrder userStrokeOrder) {
        Commodity commodity = commodityService.getById(userStrokeOrderMall.getCommodityId());
        if (null == commodity) {
            log.error("商品ID值错误: {}", userStrokeOrderMall.getCommodityId());
            throw new ApiException("商品ID值错误");
        }
        LocalDateTime now = LocalDateTime.now();
        OrderReqDTO req = new OrderReqDTO();
        req.setMobile(Optional.ofNullable(baseUserInfoService.getById(userStrokeOrder.getUserId())).map(BaseUserInfo::getMobile).orElse(""));
        req.setAppId(pandaParkConfig.getDefaultAppId());
        req.setOpenid(Optional.ofNullable(middleUserService.getUniqueByUserIdAndAppId(userStrokeOrder.getUserId(), pandaParkConfig.getDefaultAppId())).map(MiddleUser::getOpenid).orElse(""));
        req.setUserId(userStrokeOrder.getUserId());
        req.setOrderTime(DateUtil.localDateTimeToStr(now));
        req.setThirdPartyOrderId(userStrokeOrderMall.getOrderId());
        req.setSyncConfigCode(syncConfigCode);
        req.setCommodityId(userStrokeOrderMall.getCommodityId());
        req.setCommodityPrice(commodity.getCommodityPrice());
        req.setRechargeAccount(userStrokeOrderMall.getRechargeAccount());
        req.setRechargeValue(new BigDecimal(String.valueOf(userStrokeOrderMall.getQuantity())));
        req.setPayAmount(userStrokeOrder.getPayAmount());
        req.setCustomerIp(null);
        ApiResultWrapper<Object> apiResultWrapper = dataCenterService.createOrder(req);
        req.freeData();
        return apiResultWrapper;
    }
}
